#include <opencv2/opencv.hpp>
#include "MvCamera.h"

// 相机操作封装类
class HikCamera {
public:
    HikCamera() : m_pcamera(nullptr), m_bGrabbing(false) {}
    
    ~HikCamera() {
        Disconnect();
    }

    // 连接相机
    bool Connect() {
        // 1. 初始化SDK
        if (CMvCamera::InitSDK() != MV_OK) {
            return false;
        }

        // 2. 枚举设备
        MV_CC_DEVICE_INFO_LIST stDeviceList;
        memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
        int nRet = CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE | MV_GENTL_GIGE_DEVICE | MV_GENTL_CAMERALINK_DEVICE | MV_GENTL_CXP_DEVICE | MV_GENTL_XOF_DEVICE, &stDeviceList); 
        
        if (MV_OK != nRet) {
            return false;
        }

        // 3. 创建相机实例并连接
        m_pcamera = new CMvCamera();
        if (m_pcamera->Open(stDeviceList.pDeviceInfo[0]) != MV_OK) {
            delete m_pcamera;
            m_pcamera = nullptr;
            return false;
        }

        // 4. 设置采集参数
        m_pcamera->SetIntValue("Width", 1920);         // 根据实际相机调整
        m_pcamera->SetIntValue("Height", 1080);
        m_pcamera->SetEnumValue("PixelFormat", PixelType_Gvsp_BGR8_Packed);

        return true;
    }

    // 开始采集
    bool StartGrabbing() {
        if (!m_pcamera || m_bGrabbing) return false;
        
        // 设置SDK内部缓存数量
        m_pcamera->SetImageNodeNum(3);
        
        // 开始采集
        if (m_pcamera->StartGrabbing() != MV_OK) {
            return false;
        }
        
        m_bGrabbing = true;
        return true;
    }

    // 获取一帧图像
    cv::Mat GrabFrame(int timeout = 1000) {
        if (!m_pcamera || !m_bGrabbing) return cv::Mat();
        
        // 获取图像缓冲区
        MV_FRAME_OUT stImageOut = {0};
        
        if (m_pcamera->GetImageBuffer(&stImageOut, timeout) != MV_OK) {
            return cv::Mat();
        }
        
        // 转换为OpenCV Mat
        cv::Mat frame;
        ConvertToMat(stImageOut.stFrameInfo, stImageOut.pBufAddr, frame);
        
        // 释放缓冲区
        m_pcamera->FreeImageBuffer(&stImageOut);
        
        return frame;
    }

    // 停止采集
    void StopGrabbing() {
        if (m_pcamera && m_bGrabbing) {
            m_pcamera->StopGrabbing();
            m_bGrabbing = false;
        }
    }

    // 断开连接
    void Disconnect() {
        StopGrabbing();
        if (m_pcamera) {
            m_pcamera->Close();
            delete m_pcamera;
            m_pcamera = nullptr;
        }
        CMvCamera::FinalizeSDK();
    }

private:
    // 图像格式转换
    void ConvertToMat(const MV_FRAME_OUT_INFO_EX& frameInfo, unsigned char* pData, cv::Mat& outImage) {
        int cvType = 0;
        switch (frameInfo.enPixelType) {
            case PixelType_Gvsp_Mono8: 
                cvType = CV_8UC1; 
                break;
            case PixelType_Gvsp_BGR8_Packed:
                cvType = CV_8UC3;
                break;
            case PixelType_Gvsp_RGB8_Packed:
                cvType = CV_8UC3;
                break;
            case PixelType_Gvsp_BGRA8_Packed:
                cvType = CV_8UC4;
                break;
            default:
                // 处理不支持的格式
                return;
        }
        
        // 直接创建Mat引用图像数据
        outImage = cv::Mat(
            frameInfo.nHeight,
            frameInfo.nWidth,
            cvType,
            pData
        );
        
        // 需要颜色空间转换的情况
        if (frameInfo.enPixelType == PixelType_Gvsp_RGB8_Packed) {
            cv::cvtColor(outImage, outImage, cv::COLOR_RGB2BGR);
        }
    }

    CMvCamera* m_pcamera;
    bool m_bGrabbing;
};